#include "o_txr_algo_dlm_v5.h"  // 包含类声明的头文件

using namespace vino_v6;  // 使用vino_v6命名空间以直接访问其类和函数

namespace txr_algo_dlm  // 定义txr_algo_dlm命名空间用于封装算法实现
{
    // o_TxrAlgoDlmV5类的构造函数
    o_TxrAlgoDlmV5::o_TxrAlgoDlmV5()
        :m_p_detect(TK_NULL_PTR)  // 将m_p_detect初始化为TK_NULL_PTR（空指针）
    {}

    // o_TxrAlgoDlmV5类的析构函数
    o_TxrAlgoDlmV5::~o_TxrAlgoDlmV5()
    {
        Release();  // 在析构时释放资源
    }

    /**
     * @brief 加载模型的方法。
     *
     * 此函数创建Yolo_VINO对象并从指定路径加载模型权重文件。
     * 如果加载失败，它会释放已分配的资源。
     *
     * @param cfg 包含模型文件路径和其他配置信息的配置结构。
     * @return 返回加载结果，true表示成功，false表示失败。
     */
    tk_bool o_TxrAlgoDlmV5::Load(st_dlm_cfg & cfg)
    {
        m_p_detect = new Yolo_VINO();  // 创建Yolo_VINO对象
        const std::string path_weight = std::string(cfg.file_path_name) + ".hdats";  // 构造模型权重文件路径

        std::cout << "Loading weight: " << path_weight << std::endl;

        const tk_bool rt = m_p_detect->Init(path_weight.c_str());  // 初始化Yolo_VINO对象
        if (!rt)  // 如果初始化失败
        {
            std::cerr << "Failed to load weight." << std::endl;
            Release();  // 释放资源
        }
        std::cout << "Loading Success" << std::endl;
        return rt;  // 返回初始化结果
    }

    /**
     * @brief 释放资源的方法。
     *
     * 此函数释放Yolo_VINO对象占用的资源，确保不会发生内存泄漏。
     */
    void o_TxrAlgoDlmV5::Release()
    {
        SAFE_DELETE(m_p_detect);  // 安全删除m_p_detect指向的对象
    }

    /**
     * @brief 获取批处理大小的方法。
     *
     * 此函数返回当前Yolo_VINO对象的批处理大小。
     *
     * @return 返回批处理大小，如果m_p_detect为空则返回0。
     */
    tk_int32 o_TxrAlgoDlmV5::BatchSize()
    {
        if (m_p_detect)  // 如果m_p_detect不为空
        {
            return m_p_detect->BatchSize();  // 返回Yolo_VINO对象的批处理大小
        }
        return 0;  // 如果m_p_detect为空，返回0
    }

    /**
     * @brief 边界框转换函数，将DetectRes_VINO类型的边界框转换为st_box类型。
     *
     * 此函数将检测结果中的边界框转换为适合进一步处理的格式，并限制坐标范围。
     *
     * @param p_box 指向DetectRes_VINO类型的边界框数组的指针。
     * @param box_num 边界框的数量。
     * @param result 存储转换后边界框结果的结构体。
     * @param row 图像高度。
     * @param col 图像宽度。
     */
    void BoxTrans(Yolo_VINO::DetRes_VINO * p_box, tk_int32 box_num, st_result_boxes & result, tk_int32 row, tk_int32 col)
    {
        result.vaild_num = box_num;  // 设置有效边界框的数量
        for (tk_int32 i = 0; i < box_num; ++i)  // 遍历每个边界框
        {
            st_box & box = result.boxes[i];  // 获取st_box类型的边界框
            box.x = p_box[i].x - p_box[i].w / 2;  // 计算x坐标
            box.y = p_box[i].y - p_box[i].h / 2;  // 计算y坐标
            box.w = p_box[i].w;  // 宽度
            box.h = p_box[i].h;  // 高度
            box.prob = p_box[i].prob;  // 置信度
            box.obj_id = p_box[i].classes;  // 对象类别ID

            // 坐标范围限制，确保边界框坐标不超过图像边界
            box.x = qBound(0, box.x, (col - 1, box.x));
            box.y = qBound(0, box.y, (row - 1, box.y));
            box.w = qBound(0, box.w, (box.w, col - 1 - box.x));
            box.h = qBound(0, box.h, (box.h, row - 1 - box.y));
        }
    }

    /**
     * @brief 执行对象检测。
     *
     * 使用VINO进行图像预处理、推理和后处理，获取最终的检测结果。
     *
     * @param p_unit 指向输入检测单元数组的指针。
     * @param size 输入检测单元的数量。
     */
    void o_TxrAlgoDlmV5::Detect(st_detect_unit * p_unit, tk_int32 size) {
        if (size <= 0 || p_unit == nullptr) return; // 检查输入有效性

        // 动态创建st_dlm_data数组存储转换后的图像数据
        auto* dlm_data_array = new st_dlm_data[size];

        // 遍历每个st_detect_unit并将图像数据复制到st_dlm_data的image_t中
        for (int i = 0; i < size; ++i) {
            const st_detect_unit & unit = p_unit[i];
            st_dlm_data & dlm_data = dlm_data_array[i];

            // 将图像数据从st_detect_unit复制到st_dlm_data的image_t中
            dlm_data.img.rgb8 = cv::Mat(unit.img.h, unit.img.w, CV_8UC3);

            for (int row = 0; row < unit.img.h; ++row) {
                for (int col = 0; col < unit.img.w; ++col) {
                    const int idx = row * unit.img.w + col;
                    auto &pixel = dlm_data.img.rgb8.at<cv::Vec3b>(row, col);
                    pixel[0] = unit.img.pp_rgb8[2][idx]; // R
                    pixel[1] = unit.img.pp_rgb8[1][idx]; // G
                    pixel[2] = unit.img.pp_rgb8[0][idx]; // B
                }
            }
        }

        // 创建检测结果的向量
        std::vector<std::vector<Yolo_VINO::DetRes_VINO>> vv_results;

        // 执行检测，将st_dlm_data数组和大小传递给底层Detect方法
        m_p_detect->Detect(dlm_data_array, size, vv_results);

        // 释放动态分配的内存
        delete[] dlm_data_array;

        // 遍历每个图像的检测结果
        for (int i = 0; i < size; ++i)  // 遍历每个图像单元
        {
            const tk_int32 result_box_num = __min(vv_results[i].size(), C_SHARP_MAX_OBJECTS);  // 获取检测结果的数量
            st_img_rgb & rgb = p_unit[i].img;  // 获取图像数据
            BoxTrans(vv_results[i].data(), result_box_num, p_unit[i].result, rgb.h, rgb.w);  // 转换边界框并填充结果
        }
    }

}  // txr_algo_dlm命名空间结束